package com.tools.helper;

import android.util.Log;

import java.util.UUID;

public class BleParser {
    static final String TAG = "BleParser";

    // 处理广播数据
    public void parseRecord(byte[] scanRecord) {
        int startIndex = 2;
        boolean patternFound = false;
        Log.d(TAG, "handleScanResult: "+bytesToHex(scanRecord));
        // 寻找是否存在beacon以及有效数据的起始索引
        while (startIndex <= 5) {
            if (((int) scanRecord[startIndex + 2] & 0xff) == 0x02
                    && ((int) scanRecord[startIndex + 3] & 0xff) == 0x15) {
                patternFound = true;
                break;
            }
            startIndex++;
        }
        System.out.println("a==== " + patternFound);
        if (patternFound) {
            String data = parseBLEData(scanRecord, startIndex);
            Log.d(TAG, data);
        }
    }

    // 根据RSSI计算距离
    public double rssi2distance(int rssi) {
        int iRssi = Math.abs(rssi);
        // 发射端和接收端相隔1米时的信号强度
        int A = 59;
        // 环境噪声衰减因子
        double n = 2.0;
        double power = (iRssi - A) / (10 * n);
        return Math.pow(10, power);
    }

    // 格式化UUID
    public String parseUUID(String data) {
        String uuid = "";
        if (data.length() == 32) {
            uuid = data.substring(0, 8) + "-"
                    + data.substring(8, 12) + "-"
                    + data.substring(12, 16) + "-"
                    + data.substring(16, 20) + "-"
                    + data.substring(20);
        } else {
            System.out.println("toast_uuid_not_found==");
        }
        return uuid;
    }

    // 解析BLE数据
    public String parseBLEData(byte[] scanRecord, int startIndex) {
        // uuid的长度是16bytes
        byte[] uuidBytes = new byte[16];
        System.arraycopy(scanRecord, startIndex + 4, uuidBytes, 0, 16);
        String hexString = bytesToHex(uuidBytes);
        // beacon的UUID值
        String uuid = parseUUID(hexString);
        // beacon的Major值
        int major = (scanRecord[startIndex + 20] & 0xff) * 0x100
                + (scanRecord[startIndex + 21] & 0xff);
        // ibeacon的Minor值
        int minor = (scanRecord[startIndex + 22] & 0xff) * 0x100
                + (scanRecord[startIndex + 23] & 0xff);

        int txPower = (scanRecord[startIndex + 24]);
        Log.d(TAG, "onLeScan: 它的UUID是" + uuid + "，txPower是" + txPower);
        Log.d(TAG, "onLeScan: major=" + major + "，minor=" + minor);
        return "UUID：" + uuid + "\nmajor：" + major + "    minor：" + minor + "\ntxPower：" + txPower;
    }

    public static String byteToHex(byte b) {
        return Integer.toHexString(b & 0xFF);
    }

    public static String bytesToHex(byte[] data) {
        StringBuilder hexString = new StringBuilder();
        for (byte b : data) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                // 如果是一位，补0
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static int getHexUUID(UUID uuid) {
        return Integer.parseInt(uuid.toString().substring(4, 8), 16);
    }

    public static short calculateChecksum(byte[] data) {
        short checksum;
        // 计算1的补码和
        checksum = calculateOnesComplementSum(data);
        // 将1的补码和取反，即0变1，1变0，就是校验和
        checksum = (short)(~checksum);
        return checksum;
    }

    /**
     * 根据输入的字节数组数据计算16比特位的1的补码和（1's complement sum）。
     * 就是将输入数据每两个字节组成一个16比特位的整数，然后将该整数系列二进制相加，
     * 并经超过最高有效位的进位丢弃，并经该丢弃的进位加到最低有效位上。
     * @param data 输入数据
     * @return 16比特位的1的补码和
     */
    public static short calculateOnesComplementSum(byte[] data) {
        // 考虑到进位，所以中间结果用32比特位的整数存放，高位两个字节存储的是进位
        int middleSum = 0;

        for (int i = 0; i < data.length; i += 2) {
            if (data.length % 2 == 0) { // 输入数据的总字节数是偶数
                // 将两个相邻的字节组合成一个整数，并和前面的整数和相加
                middleSum += ((0xFF00 & (data[i] << 8)) | (0x00FF & data[i + 1]));
            } else {  // 输入数据的总字节数是奇数
                // 如果已经到了数据的最后一个字节，后面要补一个各bit位全为0的字节
                if (i == (data.length - 1)) {
                    middleSum += ((0xFF00 & (data[i] << 8)));
                } else {
                    middleSum += ((0xFF00 & (data[i] << 8)) | (0x00FF & data[i + 1]));
                }
            }
        }

        // 定义进位变量
        short carries;
        // 将进位取出来
        carries = (short)((middleSum & 0xFFFF0000) >> 16);
        // 因为将进位加到后面两个字节上，可能又产生了进位，所以要用循环判断处理，
        // 直到不产生进位了为止
        while (carries != 0) {
            // 将sum的前面两个字节清零，准备下面的计算
            middleSum = (middleSum & 0x0000FFFF);
            // 将进位加到后面两个字节上
            middleSum += carries;
            // 将进位再取出来，因为上面相加后可能又产生了进位
            carries = (short)((middleSum & 0xFFFF0000) >> 16);
        }

        // 将上面计算结果的低端2个字节取出来返回，就是1的补码和
        return (short)(middleSum & 0x0000FFFF);
    }
}
